package PrjMQTT

import (
	"dgo/MyProj/PrjHttpUtils"
	"dgo/goutils/utils"
	"fmt"
	"github.com/gorilla/websocket"
	"net/http"
	"strings"
	"time"
)

var (
	_ws_req_uri string                 = "/ws"
	WsSc        *utils.SubscribeCenter = nil
)

/*
*
  - 如果通道为 /topic/chat,
    WsSc 的发送和订阅
    订阅:
    "onrecv-/topic/chat": 对方发送的消息
    "oncon-/topic/chat":  连接建立
    "ondis-/topic/chat":  连接关闭
    "onsend-/topic/chat": 发送给所有订阅者的消息
*/
func OnWsRequest(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		PrjHttpUtils.ResponseCodeAndMsg(w, -1, err.Error())
		return
	}
	defer conn.Close()

	subKey := strings.TrimPrefix(r.URL.Path, _ws_req_uri)
	if len(subKey) == 0 {
		subKey = "default"
	}

	recvDispKey := fmt.Sprintf("onrecv-%s", subKey)
	sendDispKey := fmt.Sprintf("onsend-%s", subKey)
	connectedDispKey := fmt.Sprintf("oncon-%s", subKey)
	connDisDispKey := fmt.Sprintf("ondis-%s", subKey)

	str := fmt.Sprintf("[订阅消息]:[url:%s][key:%s]", r.URL.Path, subKey)
	utils.Log.Infof(str)
	var jb utils.JSONBuilder
	jb.AddObject("code", 0, "msg", str)
	conn.WriteMessage(websocket.TextMessage, jb.Bytes())

	conn.SetCloseHandler(func(code int, text string) error {
		if WsSc.UnsubscribeChannel(subKey, conn) {
			str := fmt.Sprintf("[退订成功]:[key:%s]", subKey)
			utils.Log.Infof(str)
		} else {
			str := fmt.Sprintf("[退订失败]:[key:%s]", subKey)
			utils.Log.Infof(str)
		}
		WsSc.DispatchData(connDisDispKey, conn, "disconnected", subKey)
		return nil
	})

	WsSc.DispatchData(connectedDispKey, conn, "connected", subKey)

	// 发送信息给客户端
	WsSc.SubscribeChannel(sendDispKey, conn,
		func(sender interface{}, channelid string, subscribeid interface{}, data interface{}, tag interface{}, isBreak *bool) bool {
			if str, ok := data.(string); ok {
				conn.SetWriteDeadline(time.Now().Add(time.Second * 10))
				conn.WriteMessage(websocket.TextMessage, []byte(str))
				return true
			}

			if buf, ok := data.([]byte); ok {
				conn.SetWriteDeadline(time.Now().Add(time.Second * 10))
				conn.WriteMessage(websocket.TextMessage, buf)
				return true
			}

			return false
		})

	for {
		_, recvBuf, err := conn.ReadMessage()
		if err != nil {
			golog.Debugf("read:%s", err)
			break
		} else {
			// 分发消息
			WsSc.DispatchData(recvDispKey, conn, recvBuf, subKey)
		}
	}
}

/*
**

	ws_req_uri 用Subscrible的方式传递消息
*/
func StartProjWsHandleWithSc(ws_req_uri string, sc *utils.SubscribeCenter) {
	_ws_req_uri = ws_req_uri
	WsSc = sc
	if WsSc == nil {
		WsSc = utils.NewSubscribeCenter()
	}
	http.HandleFunc(ws_req_uri+"/", OnWsRequest)
}
